<template>
  <el-button text :bg="showQuery" :type="showQuery ? 'primary' : ''" @click="handleClick">
    发布公告
  </el-button>
  <AnnouncementBox
    v-model:showDialog="showDialog"
    @release="(n) => (announcement = n)"
    v-bind="{ tableData }"
  />
</template>

<script setup>
import { ref, watch } from 'vue'
import { generateUniqueRGBColors } from '@/utils/toolsFn'
import AnnouncementBox from './AnnouncementBox.vue'
import { upsertAnnouncement } from '@/api/announcement'
import { ElMessageBox } from 'element-plus'

let queryResultLayer, drawer, filteredLayer

const drawSource = new ol.source.Vector()
const drawLayer = new ol.layer.Vector({
  source: drawSource,
  zIndex: 100,
})

const { map } = defineProps({
  map: {
    type: Object,
    required: true,
  },
})
const showQuery = ref(false)
const canDraw = ref(false)
const showDialog = ref(false)
const announcement = ref({}) //从弹窗获取的公告内容
const tableData = ref([]) //在弹窗中显示的筛选出的居民区数据

const geoJSONFormat = new ol.format.GeoJSON() //实例化GeoJSON格式对象,用于格式转换

//封装查询功能
const attQuery = () => {
  // 调用封装的函数清除之前的查询结果
  clearA()
  // 参数结构对象
  const queryStruct = new Zondy.Service.QueryFeatureStruct({
    IncludeGeometry: true, //是否包含几何信息
  })

  // 查询参数信息对象
  const queryParam = new Zondy.Service.QueryByLayerParameter(
    'gdbp://MapGisLocal/wuhan/sfcls/居民区',
    {
      struct: queryStruct,
      recordNumber: 1000, //查询记录数
    },
  )
  // 实例化矢量图层查询服务对象
  const queryService = new Zondy.Service.QueryLayerFeature(queryParam, {
    ip: '127.0.0.1',
    port: '8089',
  })
  // 执行查询操作，querySuccess为查询回调函数
  queryService.query(querySuccess, queryError)
}
// 查询失败回调
const queryError = (e) => {
  console.log(e)
}
// 查询成功回调
const querySuccess = (result) => {
  // 初始化Zondy.Format.PolygonJSON类
  const format = new Zondy.Format.PolygonJSON()
  // 将MapGIS要素JSON反序列化为ol.Feature类型数组
  const features = format.read(result)
  // 实例化一个矢量图层queryResultLayer用于显示查询结果
  queryResultLayer = new ol.layer.Vector({})
  // 设置矢量图层数据源
  const queryResultSource = new ol.source.Vector({
    features,
    wrapX: false,
  })
  queryResultLayer.setSource(queryResultSource)
  // 设置样式
  const count = features.length
  const colors = generateUniqueRGBColors(count)
  const style = (f) => {
    const index = features.indexOf(f)
    const color = colors[index]
    return new ol.style.Style({
      fill: new ol.style.Fill({
        color,
      }),
      stroke: new ol.style.Stroke({
        color: '#333',
        width: 1,
      }),
    })
  }
  queryResultLayer.setStyle(style)
  // 显示图层
  map.addLayer(queryResultLayer)
  // 实例化绘制折线功能
  initDraw()
}

// 封装绘制折线功能
const initDraw = () => {
  map.addLayer(drawLayer)
  drawer = new ol.interaction.Draw({
    source: drawSource, //绘制层数据源,双击完成
    /*取值：Point（点）、LineString（线）、Polygon（面）和Circle（圆）。*/
    type: 'LineString',
  })
  map.addInteraction(drawer)
  // 设置绘制完成后的回调, 生成缓冲区
  drawer.on('drawend', drawEnd)
}
// 绘制结束的回调
const drawEnd = (e) => {
  const feature = e.feature
  feature.setStyle(
    new ol.style.Style({
      stroke: new ol.style.Stroke({
        color: 'red',
        width: 1,
      }),
    }),
  )
  const geometry = feature.getGeometry()
  const points = geometry.getCoordinates()
  // 绘制缓冲区
  const turfLine = turf.lineString(points)
  const buffered = turf.buffer(turfLine, 100, { units: 'meters' })
  // 将buffered feature 转为openlayers feature格式
  const bufferedFeature = geoJSONFormat.readFeature(buffered)
  bufferedFeature.setStyle(
    new ol.style.Style({
      fill: new ol.style.Fill({
        color: 'rgba(255, 255, 255,0.5)',
      }),
    }),
  )
  drawSource.addFeature(bufferedFeature)
  // 进行叠加分析
  overlayAnalysis(buffered)
}
// 封装叠加分析功能
const overlayAnalysis = (buffered) => {
  const featuresArr = queryResultLayer.getSource().getFeatures() //居民区的features
  // 转换为geojson 标准feature格式判断是否重叠并返回重叠的原feature
  const { features: convertedFeatures } = geoJSONFormat.writeFeaturesObject(featuresArr)
  const filteredFeatures = featuresArr.filter((f, i) => {
    // const geometry = f.getGeometry()
    // const coordinates = geometry.getCoordinates()
    // const turfFeature = turf.polygon(coordinates)
    const turfFeature = turf.feature(convertedFeatures[i].geometry)
    return turf.booleanOverlap(buffered, turfFeature)
  })
  if (!filteredFeatures.length) {
    // 没有重叠的居民区
    ElMessageBox.alert('没有重叠的居民区', {
      callback: () => {
        drawSource.clear()
      },
    })

    return
  }
  // 显示叠加分析结果
  filteredLayer = new ol.layer.Vector({
    source: new ol.source.Vector({
      features: filteredFeatures,
    }),
  })
  // 设置样式
  const count = filteredFeatures.length
  const colors = generateUniqueRGBColors(count)
  const style = (f) => {
    const index = filteredFeatures.indexOf(f)
    const color = colors[index]
    return new ol.style.Style({
      fill: new ol.style.Fill({
        color,
      }),
      stroke: new ol.style.Stroke({
        color: '#333',
        width: 1,
      }),
    })
  }
  filteredLayer.setStyle(style)
  map.addLayer(filteredLayer)
  // 填充公告弹窗数据
  tableData.value = filteredFeatures.map((f) => {
    const { name, tel } = f.getProperties().getProperties()
    return { name, tel }
  })
  showQuery.value = false //清除原来的彩色居民区
  drawer.set('active', false) //停止绘制
  showDialog.value = true //显示公告弹窗
}

// 封装清除查询结果功能
const clearA = () => {
  if (queryResultLayer) {
    map.removeLayer(queryResultLayer)
    queryResultLayer = null
  }
}
// 封装销毁画笔功能
const destroyDraw = () => {
  map.removeLayer(drawLayer)
  drawSource.clear()
  map.removeInteraction(drawer)
  drawer = null
}

const handleClick = () => {
  showQuery.value = !showQuery.value
  canDraw.value = !canDraw.value
}

const releaseAnnouncement = async (content = '') => {
  try {
    await upsertAnnouncement(content)
    ElMessageBox.alert('发布成功', {
      type: 'success',
    })
  } catch {
    ElMessageBox.alert('发布失败', {
      type: 'error',
    })
  }
}

watch(showQuery, () => {
  if (showQuery.value) {
    // 移除之前的分析结果
    if (filteredLayer) {
      map.removeLayer(filteredLayer)
      filteredLayer = null
    }
    attQuery()
  } else clearA()
})
watch(canDraw, () => {
  if (!canDraw.value) destroyDraw()
})
watch(showDialog, () => {
  if (!showDialog.value) {
    // 公告弹窗关闭时，销毁绘制层
    canDraw.value = false
    // 移除分析结果图层
    map.removeLayer(filteredLayer)
  }
})
watch(announcement, async () => {
  // 当公告内容发生变化时，将公告内容设置为feature的属性
  if (!filteredLayer) return
  const { time, content } = announcement.value

  // 将features转为geojson字符串发送到后端
  const features = filteredLayer.getSource().getFeatures()
  features.forEach((f) => {
    f.getProperties().set('announcement', { time, content })
  })
  const geoJSONFormat = new ol.format.GeoJSON()
  const geojson = geoJSONFormat.writeFeatures(features)
  releaseAnnouncement(geojson)
})
</script>

<style scoped></style>
